#include <jni.h>
#include <vector>
#include "Wpmz.h"
#include "wpml.h"
#include "com_dji_wpmz_WpmzJni.h"

// 辅助函数：将 Java Waypoint 转换为 C++ WaypointT
wpml::WaypointT convertWaypoint(JNIEnv *env, jobject jWaypoint) {
    wpml::WaypointT waypoint;
    
    // 获取类和方法ID
    jclass waypointClass = env->GetObjectClass(jWaypoint);
    
    // 获取字段值
    waypoint.longitude = env->GetDoubleField(jWaypoint, env->GetFieldID(waypointClass, "longitude", "D"));
    waypoint.latitude = env->GetDoubleField(jWaypoint, env->GetFieldID(waypointClass, "latitude", "D"));
    waypoint.ellipsoidHeight_a = env->GetIntField(jWaypoint, env->GetFieldID(waypointClass, "ellipsoidHeight", "I"));
    waypoint.height_a = env->GetIntField(jWaypoint, env->GetFieldID(waypointClass, "height", "I"));
    waypoint.executeHeight_b = env->GetIntField(jWaypoint, env->GetFieldID(waypointClass, "executeHeight", "I"));
    waypoint.waypointSpeed_b = env->GetIntField(jWaypoint, env->GetFieldID(waypointClass, "waypointSpeed", "I"));
    waypoint.useGlobalHeight_a = env->GetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalHeight", "Z"));
    waypoint.useGlobalSpeed_a = env->GetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalSpeed", "Z"));
    waypoint.useGlobalHeadingParam_a = env->GetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalHeadingParam", "Z"));
    waypoint.useGlobalTurnParam_a = env->GetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalTurnParam", "Z"));
    waypoint.useStraightLine_b = env->GetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useStraightLine", "Z"));
    
    // 处理 headingParam
    jobject jHeadingParam = env->GetObjectField(jWaypoint, env->GetFieldID(waypointClass, "headingParam", "Lcom/dji/wpmz/WpmzJni$HeadingParam;"));
    if (jHeadingParam) {
        jclass headingParamClass = env->GetObjectClass(jHeadingParam);
        waypoint.headingParam_b.waypointHeadingMode = static_cast<wpml::WaypointHeadingMode>(
            env->GetIntField(jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingMode", "I")));
        waypoint.headingParam_b.waypointHeadingAngleEnable = env->GetBooleanField(
            jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngleEnable", "Z"));
        waypoint.headingParam_b.waypointHeadingAngle = env->GetIntField(
            jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngle", "I"));
        
        jstring jPoiPoint = (jstring)env->GetObjectField(
            jHeadingParam, env->GetFieldID(headingParamClass, "waypointPoiPoint", "Ljava/lang/String;"));
        if (jPoiPoint) {
            const char *poiPoint = env->GetStringUTFChars(jPoiPoint, nullptr);
            waypoint.headingParam_b.waypointPoiPoint = poiPoint;
            env->ReleaseStringUTFChars(jPoiPoint, poiPoint);
        }
    }
    
    // 处理 turnParam
    jobject jTurnParam = env->GetObjectField(jWaypoint, env->GetFieldID(waypointClass, "turnParam", "Lcom/dji/wpmz/WpmzJni$TurnParam;"));
    if (jTurnParam) {
        jclass turnParamClass = env->GetObjectClass(jTurnParam);
        waypoint.turnParam_b.waypointTurnMode = static_cast<wpml::WaypointTurnMode>(
            env->GetIntField(jTurnParam, env->GetFieldID(turnParamClass, "waypointTurnMode", "I")));
        waypoint.turnParam_b.waypointTurnDampingDist = env->GetIntField(
            jTurnParam, env->GetFieldID(turnParamClass, "waypointTurnDampingDist", "I"));
    }
    
    return waypoint;
}

// 辅助函数：将 Java Document 转换为 C++ Document
wpml::Document convertDocument(JNIEnv *env, jobject jDocument) {
    wpml::Document doc;
    
    // 获取类和方法ID
    jclass documentClass = env->GetObjectClass(jDocument);
    
    // 获取字段值
    doc.createTime = env->GetLongField(jDocument, env->GetFieldID(documentClass, "createTime", "J"));
    doc.updateTime = env->GetLongField(jDocument, env->GetFieldID(documentClass, "updateTime", "J"));
    
    // 处理 missionConfig
    jobject jMissionConfig = env->GetObjectField(jDocument, env->GetFieldID(documentClass, "missionConfig", "Lcom/dji/wpmz/WpmzJni$MissionConfig;"));
    if (jMissionConfig) {
        jclass missionConfigClass = env->GetObjectClass(jMissionConfig);
        doc.missionConfig.flyToWaylineMode = static_cast<wpml::FlyToWaylineMode>(
            env->GetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "flyToWaylineMode", "I")));
        doc.missionConfig.finishAction = static_cast<wpml::FinishAction>(
            env->GetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "finishAction", "I")));
        doc.missionConfig.exitOnRCLost = static_cast<wpml::ExitOnRCLost>(
            env->GetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "exitOnRCLost", "I")));
        doc.missionConfig.takeOffSecurityHeight = env->GetIntField(
            jMissionConfig, env->GetFieldID(missionConfigClass, "takeOffSecurityHeight", "I"));
        doc.missionConfig.globalTransitionalSpeed = env->GetIntField(
            jMissionConfig, env->GetFieldID(missionConfigClass, "globalTransitionalSpeed", "I"));
        
        // 处理 droneInfo
        jobject jDroneInfo = env->GetObjectField(jMissionConfig, env->GetFieldID(missionConfigClass, "droneInfo", "Lcom/dji/wpmz/WpmzJni$DroneInfo;"));
        if (jDroneInfo) {
            jclass droneInfoClass = env->GetObjectClass(jDroneInfo);
            doc.missionConfig.droneInfo.droneEnumValue = env->GetIntField(
                jDroneInfo, env->GetFieldID(droneInfoClass, "droneEnumValue", "I"));
            doc.missionConfig.droneInfo.droneSubEnumValue = env->GetIntField(
                jDroneInfo, env->GetFieldID(droneInfoClass, "droneSubEnumValue", "I"));
        }
        
        // 处理 payloadInfo
        jobject jPayloadInfo = env->GetObjectField(jMissionConfig, env->GetFieldID(missionConfigClass, "payloadInfo", "Lcom/dji/wpmz/WpmzJni$PayloadInfo;"));
        if (jPayloadInfo) {
            jclass payloadInfoClass = env->GetObjectClass(jPayloadInfo);
            doc.missionConfig.payloadInfo.payloadEnumValue = env->GetIntField(
                jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadEnumValue", "I"));
            doc.missionConfig.payloadInfo.payloadSubEnumValue = env->GetIntField(
                jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadSubEnumValue", "I"));
            doc.missionConfig.payloadInfo.payloadPositionIndex = env->GetIntField(
                jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadPositionIndex", "I"));
        }
    }
    
    // 处理 wayline
    jobject jWayline = env->GetObjectField(jDocument, env->GetFieldID(documentClass, "wayline", "Lcom/dji/wpmz/WpmzJni$Wayline;"));
    if (jWayline) {
        jclass waylineClass = env->GetObjectClass(jWayline);
        doc.wayline.templateType_a = static_cast<wpml::TemplateType>(
            env->GetIntField(jWayline, env->GetFieldID(waylineClass, "templateType", "I")));
        doc.wayline.gimbalPitchMode_a = static_cast<wpml::GimbalPitchMode>(
            env->GetIntField(jWayline, env->GetFieldID(waylineClass, "gimbalPitchMode", "I")));
        doc.wayline.globalWaypointTurnMode = static_cast<wpml::WaypointTurnMode>(
            env->GetIntField(jWayline, env->GetFieldID(waylineClass, "globalWaypointTurnMode", "I")));
        doc.wayline.executeHeightMode_b = static_cast<wpml::HeightMode>(
            env->GetIntField(jWayline, env->GetFieldID(waylineClass, "executeHeightMode", "I")));
        doc.wayline.useGlobalTransitionalSpeed_a = env->GetBooleanField(
            jWayline, env->GetFieldID(waylineClass, "useGlobalTransitionalSpeed", "Z"));
        doc.wayline.caliFlightEnable_a = env->GetBooleanField(
            jWayline, env->GetFieldID(waylineClass, "caliFlightEnable", "Z"));
        doc.wayline.templateId = env->GetIntField(jWayline, env->GetFieldID(waylineClass, "templateId", "I"));
        doc.wayline.autoFlightSpeed = env->GetIntField(jWayline, env->GetFieldID(waylineClass, "autoFlightSpeed", "I"));
        doc.wayline.transitionalSpeed_a = env->GetIntField(jWayline, env->GetFieldID(waylineClass, "transitionalSpeed", "I"));
        doc.wayline.waylineId_b = env->GetIntField(jWayline, env->GetFieldID(waylineClass, "waylineId", "I"));
        doc.wayline.distance_b = env->GetDoubleField(jWayline, env->GetFieldID(waylineClass, "distance", "D"));
        doc.wayline.duration_b = env->GetDoubleField(jWayline, env->GetFieldID(waylineClass, "duration", "D"));
        
        // 处理 coordinateSysParam
        jobject jCoordSysParam = env->GetObjectField(jWayline, env->GetFieldID(waylineClass, "coordinateSysParam", "Lcom/dji/wpmz/WpmzJni$CoordinateSysParam;"));
        if (jCoordSysParam) {
            jclass coordSysParamClass = env->GetObjectClass(jCoordSysParam);
            doc.wayline.coordinateSysParam_a.coordinateMode = static_cast<wpml::CoordinateMode>(
                env->GetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "coordinateMode", "I")));
            doc.wayline.coordinateSysParam_a.heightMode = static_cast<wpml::HeightMode>(
                env->GetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "heightMode", "I")));
            doc.wayline.coordinateSysParam_a.positioningType = static_cast<wpml::PositioningType>(
                env->GetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "positioningType", "I")));
            doc.wayline.coordinateSysParam_a.globalHeight = env->GetIntField(
                jCoordSysParam, env->GetFieldID(coordSysParamClass, "globalHeight", "I"));
        }
        
        // 处理 globalHeadingParam
        jobject jGlobalHeadingParam = env->GetObjectField(jWayline, env->GetFieldID(waylineClass, "globalHeadingParam", "Lcom/dji/wpmz/WpmzJni$HeadingParam;"));
        if (jGlobalHeadingParam) {
            jclass headingParamClass = env->GetObjectClass(jGlobalHeadingParam);
            doc.wayline.globalHeadingParam_a.waypointHeadingMode = static_cast<wpml::WaypointHeadingMode>(
                env->GetIntField(jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingMode", "I")));
            doc.wayline.globalHeadingParam_a.waypointHeadingAngleEnable = env->GetBooleanField(
                jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngleEnable", "Z"));
            doc.wayline.globalHeadingParam_a.waypointHeadingAngle = env->GetIntField(
                jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngle", "I"));
            
            jstring jPoiPoint = (jstring)env->GetObjectField(
                jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointPoiPoint", "Ljava/lang/String;"));
            if (jPoiPoint) {
                const char *poiPoint = env->GetStringUTFChars(jPoiPoint, nullptr);
                doc.wayline.globalHeadingParam_a.waypointPoiPoint = poiPoint;
                env->ReleaseStringUTFChars(jPoiPoint, poiPoint);
            }
        }
        
        // 处理 waypoints
        jobject jWaypoints = env->GetObjectField(jWayline, env->GetFieldID(waylineClass, "waypoints", "Ljava/util/List;"));
        if (jWaypoints) {
            jclass listClass = env->GetObjectClass(jWaypoints);
            jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
            jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
            
            jint size = env->CallIntMethod(jWaypoints, sizeMethod);
            for (int i = 0; i < size; i++) {
                jobject jWaypoint = env->CallObjectMethod(jWaypoints, getMethod, i);
                doc.wayline.waypoints.push_back(convertWaypoint(env, jWaypoint));
            }
        }
    }
    
    return doc;
}

// 辅助函数：将 C++ WaypointT 转换为 Java Waypoint
jobject convertWaypointToJava(JNIEnv *env, const wpml::WaypointT &waypoint) {
    jclass waypointClass = env->FindClass("com/dji/wpmz/WpmzJni$Waypoint");
    jmethodID constructor = env->GetMethodID(waypointClass, "<init>", "()V");
    jobject jWaypoint = env->NewObject(waypointClass, constructor);
    
    // 设置基本字段
    env->SetDoubleField(jWaypoint, env->GetFieldID(waypointClass, "longitude", "D"), waypoint.longitude);
    env->SetDoubleField(jWaypoint, env->GetFieldID(waypointClass, "latitude", "D"), waypoint.latitude);
    env->SetIntField(jWaypoint, env->GetFieldID(waypointClass, "ellipsoidHeight", "I"), waypoint.ellipsoidHeight_a);
    env->SetIntField(jWaypoint, env->GetFieldID(waypointClass, "height", "I"), waypoint.height_a);
    env->SetIntField(jWaypoint, env->GetFieldID(waypointClass, "executeHeight", "I"), waypoint.executeHeight_b);
    env->SetIntField(jWaypoint, env->GetFieldID(waypointClass, "waypointSpeed", "I"), waypoint.waypointSpeed_b);
    env->SetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalHeight", "Z"), waypoint.useGlobalHeight_a);
    env->SetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalSpeed", "Z"), waypoint.useGlobalSpeed_a);
    env->SetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalHeadingParam", "Z"), waypoint.useGlobalHeadingParam_a);
    env->SetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useGlobalTurnParam", "Z"), waypoint.useGlobalTurnParam_a);
    env->SetBooleanField(jWaypoint, env->GetFieldID(waypointClass, "useStraightLine", "Z"), waypoint.useStraightLine_b);
    
    // 设置 headingParam
    jclass headingParamClass = env->FindClass("com/dji/wpmz/WpmzJni$HeadingParam");
    jmethodID headingConstructor = env->GetMethodID(headingParamClass, "<init>", "()V");
    jobject jHeadingParam = env->NewObject(headingParamClass, headingConstructor);
    
    env->SetIntField(jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingMode", "I"), 
                     static_cast<jint>(waypoint.headingParam_b.waypointHeadingMode));
    env->SetBooleanField(jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngleEnable", "Z"), 
                         waypoint.headingParam_b.waypointHeadingAngleEnable);
    env->SetIntField(jHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngle", "I"), 
                     waypoint.headingParam_b.waypointHeadingAngle);
    
    jstring jPoiPoint = env->NewStringUTF(waypoint.headingParam_b.waypointPoiPoint.c_str());
    env->SetObjectField(jHeadingParam, env->GetFieldID(headingParamClass, "waypointPoiPoint", "Ljava/lang/String;"), jPoiPoint);
    
    env->SetObjectField(jWaypoint, env->GetFieldID(waypointClass, "headingParam", "Lcom/dji/wpmz/WpmzJni$HeadingParam;"), jHeadingParam);
    
    // 设置 turnParam
    jclass turnParamClass = env->FindClass("com/dji/wpmz/WpmzJni$TurnParam");
    jmethodID turnConstructor = env->GetMethodID(turnParamClass, "<init>", "()V");
    jobject jTurnParam = env->NewObject(turnParamClass, turnConstructor);
    
    env->SetIntField(jTurnParam, env->GetFieldID(turnParamClass, "waypointTurnMode", "I"), 
                     static_cast<jint>(waypoint.turnParam_b.waypointTurnMode));
    env->SetIntField(jTurnParam, env->GetFieldID(turnParamClass, "waypointTurnDampingDist", "I"), 
                     waypoint.turnParam_b.waypointTurnDampingDist);
    
    env->SetObjectField(jWaypoint, env->GetFieldID(waypointClass, "turnParam", "Lcom/dji/wpmz/WpmzJni$TurnParam;"), jTurnParam);
    
    return jWaypoint;
}

// 辅助函数：将 C++ Document 转换为 Java Document
jobject convertDocumentToJava(JNIEnv *env, const wpml::Document &doc) {
    jclass documentClass = env->FindClass("com/dji/wpmz/WpmzJni$Document");
    jmethodID constructor = env->GetMethodID(documentClass, "<init>", "()V");
    jobject jDocument = env->NewObject(documentClass, constructor);
    
    // 设置基本字段
    env->SetLongField(jDocument, env->GetFieldID(documentClass, "createTime", "J"), doc.createTime);
    env->SetLongField(jDocument, env->GetFieldID(documentClass, "updateTime", "J"), doc.updateTime);
    
    // 设置 missionConfig
    jclass missionConfigClass = env->FindClass("com/dji/wpmz/WpmzJni$MissionConfig");
    jmethodID missionConfigConstructor = env->GetMethodID(missionConfigClass, "<init>", "()V");
    jobject jMissionConfig = env->NewObject(missionConfigClass, missionConfigConstructor);
    
    env->SetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "flyToWaylineMode", "I"), 
                     static_cast<jint>(doc.missionConfig.flyToWaylineMode));
    env->SetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "finishAction", "I"), 
                     static_cast<jint>(doc.missionConfig.finishAction));
    env->SetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "exitOnRCLost", "I"), 
                     static_cast<jint>(doc.missionConfig.exitOnRCLost));
    env->SetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "takeOffSecurityHeight", "I"), 
                     doc.missionConfig.takeOffSecurityHeight);
    env->SetIntField(jMissionConfig, env->GetFieldID(missionConfigClass, "globalTransitionalSpeed", "I"), 
                     doc.missionConfig.globalTransitionalSpeed);
    
    // 设置 droneInfo
    jclass droneInfoClass = env->FindClass("com/dji/wpmz/WpmzJni$DroneInfo");
    jmethodID droneInfoConstructor = env->GetMethodID(droneInfoClass, "<init>", "()V");
    jobject jDroneInfo = env->NewObject(droneInfoClass, droneInfoConstructor);
    
    env->SetIntField(jDroneInfo, env->GetFieldID(droneInfoClass, "droneEnumValue", "I"), 
                     doc.missionConfig.droneInfo.droneEnumValue);
    env->SetIntField(jDroneInfo, env->GetFieldID(droneInfoClass, "droneSubEnumValue", "I"), 
                     doc.missionConfig.droneInfo.droneSubEnumValue);
    
    env->SetObjectField(jMissionConfig, env->GetFieldID(missionConfigClass, "droneInfo", "Lcom/dji/wpmz/WpmzJni$DroneInfo;"), jDroneInfo);
    
    // 设置 payloadInfo
    jclass payloadInfoClass = env->FindClass("com/dji/wpmz/WpmzJni$PayloadInfo");
    jmethodID payloadInfoConstructor = env->GetMethodID(payloadInfoClass, "<init>", "()V");
    jobject jPayloadInfo = env->NewObject(payloadInfoClass, payloadInfoConstructor);
    
    env->SetIntField(jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadEnumValue", "I"), 
                     doc.missionConfig.payloadInfo.payloadEnumValue);
    env->SetIntField(jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadSubEnumValue", "I"), 
                     doc.missionConfig.payloadInfo.payloadSubEnumValue);
    env->SetIntField(jPayloadInfo, env->GetFieldID(payloadInfoClass, "payloadPositionIndex", "I"), 
                     doc.missionConfig.payloadInfo.payloadPositionIndex);
    
    env->SetObjectField(jMissionConfig, env->GetFieldID(missionConfigClass, "payloadInfo", "Lcom/dji/wpmz/WpmzJni$PayloadInfo;"), jPayloadInfo);
    
    env->SetObjectField(jDocument, env->GetFieldID(documentClass, "missionConfig", "Lcom/dji/wpmz/WpmzJni$MissionConfig;"), jMissionConfig);
    
    // 设置 wayline
    jclass waylineClass = env->FindClass("com/dji/wpmz/WpmzJni$Wayline");
    jmethodID waylineConstructor = env->GetMethodID(waylineClass, "<init>", "()V");
    jobject jWayline = env->NewObject(waylineClass, waylineConstructor);
    
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "templateType", "I"), 
                     static_cast<jint>(doc.wayline.templateType_a));
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "gimbalPitchMode", "I"), 
                     static_cast<jint>(doc.wayline.gimbalPitchMode_a));
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "globalWaypointTurnMode", "I"), 
                     static_cast<jint>(doc.wayline.globalWaypointTurnMode));
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "executeHeightMode", "I"), 
                     static_cast<jint>(doc.wayline.executeHeightMode_b));
    env->SetBooleanField(jWayline, env->GetFieldID(waylineClass, "useGlobalTransitionalSpeed", "Z"), 
                         doc.wayline.useGlobalTransitionalSpeed_a);
    env->SetBooleanField(jWayline, env->GetFieldID(waylineClass, "caliFlightEnable", "Z"), 
                         doc.wayline.caliFlightEnable_a);
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "templateId", "I"), doc.wayline.templateId);
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "autoFlightSpeed", "I"), doc.wayline.autoFlightSpeed);
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "transitionalSpeed", "I"), doc.wayline.transitionalSpeed_a);
    env->SetIntField(jWayline, env->GetFieldID(waylineClass, "waylineId", "I"), doc.wayline.waylineId_b);
    env->SetDoubleField(jWayline, env->GetFieldID(waylineClass, "distance", "D"), doc.wayline.distance_b);
    env->SetDoubleField(jWayline, env->GetFieldID(waylineClass, "duration", "D"), doc.wayline.duration_b);
    
    // 设置 coordinateSysParam
    jclass coordSysParamClass = env->FindClass("com/dji/wpmz/WpmzJni$CoordinateSysParam");
    jmethodID coordSysParamConstructor = env->GetMethodID(coordSysParamClass, "<init>", "()V");
    jobject jCoordSysParam = env->NewObject(coordSysParamClass, coordSysParamConstructor);
    
    env->SetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "coordinateMode", "I"), 
                     static_cast<jint>(doc.wayline.coordinateSysParam_a.coordinateMode));
    env->SetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "heightMode", "I"), 
                     static_cast<jint>(doc.wayline.coordinateSysParam_a.heightMode));
    env->SetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "positioningType", "I"), 
                     static_cast<jint>(doc.wayline.coordinateSysParam_a.positioningType));
    env->SetIntField(jCoordSysParam, env->GetFieldID(coordSysParamClass, "globalHeight", "I"), 
                     doc.wayline.coordinateSysParam_a.globalHeight);
    
    env->SetObjectField(jWayline, env->GetFieldID(waylineClass, "coordinateSysParam", "Lcom/dji/wpmz/WpmzJni$CoordinateSysParam;"), jCoordSysParam);
    
    // 设置 globalHeadingParam
    jclass headingParamClass = env->FindClass("com/dji/wpmz/WpmzJni$HeadingParam");
    jmethodID headingConstructor = env->GetMethodID(headingParamClass, "<init>", "()V");
    jobject jGlobalHeadingParam = env->NewObject(headingParamClass, headingConstructor);
    
    env->SetIntField(jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingMode", "I"), 
                     static_cast<jint>(doc.wayline.globalHeadingParam_a.waypointHeadingMode));
    env->SetBooleanField(jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngleEnable", "Z"), 
                         doc.wayline.globalHeadingParam_a.waypointHeadingAngleEnable);
    env->SetIntField(jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointHeadingAngle", "I"), 
                     doc.wayline.globalHeadingParam_a.waypointHeadingAngle);
    
    jstring jPoiPoint = env->NewStringUTF(doc.wayline.globalHeadingParam_a.waypointPoiPoint.c_str());
    env->SetObjectField(jGlobalHeadingParam, env->GetFieldID(headingParamClass, "waypointPoiPoint", "Ljava/lang/String;"), jPoiPoint);
    
    env->SetObjectField(jWayline, env->GetFieldID(waylineClass, "globalHeadingParam", "Lcom/dji/wpmz/WpmzJni$HeadingParam;"), jGlobalHeadingParam);
    
    // 设置 waypoints
    jclass listClass = env->FindClass("java/util/ArrayList");
    jmethodID listConstructor = env->GetMethodID(listClass, "<init>", "()V");
    jmethodID addMethod = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
    
    jobject jWaypoints = env->NewObject(listClass, listConstructor);
    for (const auto &waypoint : doc.wayline.waypoints) {
        jobject jWaypoint = convertWaypointToJava(env, waypoint);
        env->CallBooleanMethod(jWaypoints, addMethod, jWaypoint);
    }
    
    env->SetObjectField(jWayline, env->GetFieldID(waylineClass, "waypoints", "Ljava/util/List;"), jWaypoints);
    
    env->SetObjectField(jDocument, env->GetFieldID(documentClass, "wayline", "Lcom/dji/wpmz/WpmzJni$Wayline;"), jWayline);
    
    return jDocument;
}

// JNI 方法实现
JNIEXPORT jbyteArray JNICALL Java_com_dji_wpmz_WpmzJni_pack
  (JNIEnv *env, jobject obj, jobject jDocument) {
    try {
        // 转换 Java Document 为 C++ Document
        wpml::Document doc = convertDocument(env, jDocument);
        
        // 调用 Wpmz::Pack
        std::vector<char> packedData = Wpmz::Pack(doc);
        
        // 将结果转换为 Java byte array
        jbyteArray result = env->NewByteArray(packedData.size());
        env->SetByteArrayRegion(result, 0, packedData.size(), reinterpret_cast<const jbyte*>(packedData.data()));
        
        return result;
    } catch (const std::exception &e) {
        env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
        return nullptr;
    }
}

JNIEXPORT jobject JNICALL Java_com_dji_wpmz_WpmzJni_unpack
  (JNIEnv *env, jobject obj, jbyteArray jData) {
    try {
        // 获取字节数组数据
        jsize length = env->GetArrayLength(jData);
        jbyte* data = env->GetByteArrayElements(jData, nullptr);
        
        // 转换为 vector
        std::vector<char> packedData(data, data + length);
        env->ReleaseByteArrayElements(jData, data, JNI_ABORT);
        
        // 调用 Wpmz::Unpack
        wpml::Document doc = Wpmz::Unpack(packedData);
        
        // 转换 C++ Document 为 Java Document
        return convertDocumentToJava(env, doc);
    } catch (const std::exception &e) {
        env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
        return nullptr;
    }
}

JNIEXPORT jstring JNICALL Java_com_dji_wpmz_WpmzJni_toTemplate
  (JNIEnv *env, jobject obj, jobject jDocument) {
    try {
        // 转换 Java Document 为 C++ Document
        wpml::Document doc = convertDocument(env, jDocument);
        
        // 调用 wpml::toTemplate
        std::string result = wpml::toTemplate(doc);
        
        // 将结果转换为 Java String
        return env->NewStringUTF(result.c_str());
    } catch (const std::exception &e) {
        env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
        return nullptr;
    }
}

JNIEXPORT jstring JNICALL Java_com_dji_wpmz_WpmzJni_toWaylines
  (JNIEnv *env, jobject obj, jobject jDocument) {
    try {
        // 转换 Java Document 为 C++ Document
        wpml::Document doc = convertDocument(env, jDocument);
        
        // 调用 wpml::toWaylines
        std::string result = wpml::toWaylines(doc);
        
        // 将结果转换为 Java String
        return env->NewStringUTF(result.c_str());
    } catch (const std::exception &e) {
        env->ThrowNew(env->FindClass("java/lang/RuntimeException"), e.what());
        return nullptr;
    }
}